package com.gc.cscott.cli;

import com.gc.cscott.domain.Executable;
import com.gc.cscott.domain.Solution;
import com.gc.cscott.domain.contest.Contest;
import com.gc.cscott.fs.FileSystemWorker;
import com.gc.cscott.run.Chaser;
import com.gc.cscott.run.Chaser.ChaseResult;
import com.gc.cscott.run.Executor;
import com.gc.cscott.domain.Competitor;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FilenameUtils;

/**
 *
 * @author root
 */
public class CompileCommand implements Command {

    private static final Logger log = Logger.getLogger(CompileCommand.class.getSimpleName());
    @Inject
    Contest contest;
    @Inject
    FileSystemWorker fsWorker;
    @Inject
    Executor executor;
    @Inject
    Chaser chaser;

    public List<String> listHelp() {
        return Arrays.asList("Compiles all source files in competitor's directories.",
                "List required extentions to be compiled, e.g. pas, cpp.");
    }

    public List<String> perform(List<String> args) {
        Set<String> extToCompile = ImmutableSet.copyOf(Iterables.transform(args, new Function<String, String>() {

            @Override
            public String apply(String from) {
                return from.toString();
            }
        }));
        log.log(Level.INFO, "Will compile only: " + extToCompile + " solutions");
        for (Competitor competitor : fsWorker.listCompetitorsAll()) {
            log.log(Level.INFO, "Compile {0} solutions ({1})", new Object[]{competitor.getName(), competitor.getBasedir().getPath()});
            for (Solution solution : fsWorker.listSolutions(competitor)) {
                log.log(Level.INFO, "  Solution: {0}", solution.getSolutionBase().getPath());
                try {
                    Executable source = fsWorker.findSourceInSolution(solution);
                    String ext = FilenameUtils.getExtension(source.getExecutableFilePath().getName()).toLowerCase();
                    log.log(Level.INFO, "    Source: [{1}]{0}", new Object[]{source.getExecutableFilePath().getName(), ext});
                    if (extToCompile.contains(ext)) {
                        try {
                            Process compiler = executor.runExecutable(source, source.getPlatform().getCompile(), solution.getSolutionBase());
                            ChaseResult result = chaser.chase(compiler, 60000L);
                            if (result.getExitCode() == 0 && result.isTimeout() == false) {
                                log.info("    COMPILED SUCCESSFULLY");
                            } else {
                                log.log(Level.INFO, "    exit code: {0}", result.getExitCode());
                                log.log(Level.INFO, "    stdout:\n{0}EOF", result.getStdout());
                                log.log(Level.INFO, "    stderr:\n{0}EOF", result.getStderr());
                            }
                        } catch (IOException ex) {
                            log.log(Level.SEVERE, "    Failed to start command: {0}", ex.getMessage());
                        }
                    } else {
                        log.log(Level.INFO, "      Ignored.");
                    }
                } catch (FileNotFoundException ex) {
                    log.log(Level.SEVERE, "    No source file in: {0}", solution.getSolutionBase().getAbsolutePath());
                }
            }
        }
        return ImmutableList.of();
    }
}
